﻿using CustomComponents.CustomInputBox;
using ParkSaleForAdmin.Data;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;

namespace ParkSaleForAdmin.Foundation
{

    public class BaseDataHelper
    {
        public static T Parse<T>(DatabaseData data) where T : class, new()
        {
            T obj = new T();
            Type t = obj.GetType();
            var prs = new List<PropertyInfo>(t.GetProperties());
            foreach (var i in data.Detail)
            {
                var item = prs.Find(delegate (PropertyInfo info)
                {
                    var att = info.GetCustomAttribute<DataToUIAttribute>();
                    bool x;
                    if (att != null)
                    {
                        if (att.Value == null)
                        {
                            x = info.Name.Equals(i.Name);
                            if (x)
                            {
                                info.SetValue(obj, i.Value);
                            }
                        }
                        else
                        {
                            x = att.Value.Equals(i.Name);
                            if (x)
                            {
                                info.SetValue(obj, i.Value);
                            }
                        }
                        return x;
                    }
                    else
                        return false;
                });
            }
            return obj;
        }
    }

    public partial class DatabaseManager : Window
    {
        public DatabaseManager()
        {
            InitializeComponent();
        }
    }


    /// <summary>
    /// DatabaseManager.xaml 的交互逻辑
    /// </summary>
    public abstract class DatabaseWindows<T> : DatabaseManager where T : class, new()
    {
        public int page = 0;
        public int per = 5;
        ObservableCollection<T> CollectionModelFile = new ObservableCollection<T>();
        protected virtual string[] values
        {
            get => fvalue;
        }
        protected virtual string[] titles
        {
            get => ftitle;
        }
        protected virtual string[] InputBoxTitle
        {
            get => ititle;
        }
        protected virtual string[] InputBoxValue
        {
            get => ivalue;
        }
        string[] bindname, ititle, ivalue, ftitle, fvalue;
        protected virtual string[] BindingName
        {
            get => bindname;
        }
        protected virtual void BeginToCreate()
        {
            InitializeComponent();
            findBindName(out bindname, out ititle, out ivalue, out ftitle, out fvalue);
            this.add.Click += add_Click;
            this.delete.Click += delete_Click;
            this.change.Click += change_Click;
            this.pagechange_last.Click += pagechange_last_Click;
            this.pagechange_next.Click += pagechange_Click;
            this.find.Click += Find_Click;
            this.jump.Click += Jump_Click;
            notice.MouseDoubleClick += Notice_MouseDoubleClick;

            if (values.Length != titles.Length || values.Length != BindingName.Length || titles.Length != BindingName.Length)
                throw new Exception("错误对象个数");
            if (InputBoxTitle.Length != InputBoxValue.Length)
            {
                throw new Exception("输入区域错误对象个数");
            }
            for (int i = 0; i < BindingName.Length; i++)
            {
                var item = new GridViewColumn() { Width = 140, DisplayMemberBinding = new Binding(BindingName[i]), Header = titles[i] };
                this.Columns.Columns.Add(item);
            }

            InitInputBox();
            UpdatePage();
        }
        void findBindName(out string[] bindingname, out string[] inputtitle, out string[] inputvalue, out string[] titles, out string[] values)
        {
            List<string> binds = new List<string>();
            List<string> ititles = new List<string>();
            List<string> ivalues = new List<string>();
            List<string> ftitles = new List<string>();
            List<string> fvalues = new List<string>();
            Type type = typeof(T);
            var arr = type.GetProperties();
            for (int i = 0; i < arr.Length; i++)
            {
                DataToUIAttribute[] att = (DataToUIAttribute[])arr[i].GetCustomAttributes(typeof(DataToUIAttribute), false);
                if (att != null)
                {
                    if (att.Length > 0)
                    {
                        var a = att[0];
                        if (a.Editable)
                        {
                            ititles.Add(a.Title);
                            ivalues.Add(a.Value != null ? a.Value : arr[i].Name);
                        }
                        ftitles.Add(a.Title);
                        fvalues.Add(a.Value != null ? a.Value : arr[i].Name);
                        binds.Add(arr[i].Name);
                        continue;
                    }
                }
            }
            bindingname = binds.ToArray();
            inputtitle = ititles.ToArray();
            inputvalue = ivalues.ToArray();
            titles = ftitles.ToArray();
            values = fvalues.ToArray();
        }
        public abstract string TableName
        {
            get;
        }
        public abstract string DeleteStr(T obj);
        public abstract string AppendStr(T obj);
        public abstract string ChangeStr(T obj);


        private void Jump_Click(object sender, RoutedEventArgs e)
        {
            InputBox box = new InputBox();
            string t = box.Show("请输入页数", "输入");
            try
            {
                int v = int.Parse(t);
                UpdatePage(v);
            }
            catch
            {
                MessageBox.Show("不是数字，请输入整数", "请输入错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }

        }

        private void Notice_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            UpdatePage(page);
        }

        void findtarget(int result, Type type, string v, List<T> found, string col, int j)
        {
            if (result == 2)
            {
                foreach (var i in pagedata)
                {
                    object va = type.GetProperty(col).GetValue(i);
                    if (va.ToString().Equals(v))
                    {
                        found.Add(i);
                    }
                }
                UpdatePage(j + 1, false, delegate (int r)
                {
                    findtarget(r, type, v, found, col, j + 1);
                });
            }
            else if (result == -1)
            {
                MessageBox.Show("网络错误", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void Find_Click(object sender, RoutedEventArgs e)
        {
            Type type = typeof(T);
            SingleOptionInputBox input = new SingleOptionInputBox(titles);
            List<T> found = new List<T>();
            int select = input.Show("请选择根据的数据", "输入");
            if (select >= 0)
            {
                InputBox text = new InputBox();
                string v = text.Show("请输入您指定的值", "输入");
                string col = BindingName[select];
                UpdatePage(0, false, delegate (int result)
                {
                    findtarget(result, type, v, found, col, 0);

                });
                listView.ItemsSource = found;
            }


        }

        protected void StatusUpdate(string content, bool isshow)
        {
            status.Content = content;
            if (isshow)
                status.BeginAnimation(StatusBar.OpacityProperty, new System.Windows.Media.Animation.DoubleAnimation() { From = 0, To = 1, AutoReverse = false, Duration = new Duration(TimeSpan.FromSeconds(1.5)), RepeatBehavior = new System.Windows.Media.Animation.RepeatBehavior(1) });
            else
                status.BeginAnimation(StatusBar.OpacityProperty, new System.Windows.Media.Animation.DoubleAnimation() { From = 1, To = 0, AutoReverse = false, Duration = new Duration(TimeSpan.FromSeconds(1.5)), RepeatBehavior = new System.Windows.Media.Animation.RepeatBehavior(1) });

        }


        protected virtual void InitInputBox()
        {
            for (int i = 0; i < InputBoxTitle.Length; i++)
            {
                inputbox.Items.Add(new InputPanel() { Name = InputBoxTitle[i], Tag = InputBoxValue[i] });
            }
        }
        bool updating = false;
        public bool Updating
        {
            get => updating;
            set
            {
                if (value)
                {
                    pagechange_next.IsEnabled = false;
                    pagechange_last.IsEnabled = false;
                }
                else
                {
                    pagechange_next.IsEnabled = true;
                    pagechange_last.IsEnabled = true;
                }
                updating = value;
            }
        }
        List<T> pagedata = new List<T>();

        protected const int Update = 0, Append = 1, Delete = 2, Find = 3;

        protected virtual void BeforeRequest(int request)
        {
            switch (request)
            {
                case Update:
                    StatusUpdate("正在修改...", true);
                    break;
                case Append:
                    StatusUpdate("正在新增...", true);
                    break;
                case Delete:
                    StatusUpdate("正在删除...", true);
                    break;
                case Find:
                    StatusUpdate("正在查找...", true);
                    break;
            }
        }

        protected virtual int UpdateResult(object objs, bool needtoUI = true)
        {

            if (objs != null)
            {
                var datas = (List<DatabaseData>)objs;
                if (datas.Count > 0)
                {
                    if (needtoUI)
                    {
                        CollectionModelFile.Clear();
                        foreach (var d in datas)
                        {
                            CollectionModelFile.Add(BaseDataHelper.Parse<T>(d));
                        }
                        listView.ItemsSource = CollectionModelFile;
                        return 1;
                    }
                    else
                    {
                        pagedata.Clear();
                        foreach (var d in datas)
                        {
                            pagedata.Add(BaseDataHelper.Parse<T>(d));
                        }
                        return 2;
                    }

                }
                else
                {
                    return 0;
                }

            }
            else
                return -1;
        }
        public void UpdatePage(int page = 0, bool needtoUI = true, Action<int> afterupdate = null)
        {
            if (!Updating)
            {
                Updating = true;

                SystemManager.Request<List<DatabaseData>>(SuUserRequestInfo.s_FindValue, new string[] { TableName, $"Limit {page * per},{per}" }, SystemManager.Admin, delegate (Object objs)
                {
                    AfterRequest(Find);
                    int handle = UpdateResult(objs, needtoUI);
                    if (handle == 1)
                    {
                        this.page = page;
                        notice.Content = $"页数：{page}";
                    }
                    Updating = false;
                    if (afterupdate != null)
                        afterupdate(handle);

                }, delegate ()
                {
                    BeforeRequest(Find);
                });
            }

        }
        protected virtual void AfterRequest(int type)
        {
            StatusUpdate(status.Content.ToString(), false);
        }

        public abstract void DeleteResult(Object result);
        public abstract void AppendResult(Object result);

        public abstract void ChangeResult(Object result);
        protected virtual void delete_Click(object sender, RoutedEventArgs e)
        {
            if (listView.SelectedItem != null)
            {
                var detial = (T)listView.SelectedItem;
                SystemManager.Request<int>(SuUserRequestInfo.s_DeleteValue, new string[] { TableName, DeleteStr(detial) }, SystemManager.Admin, delegate (Object obj)
                 {
                     AfterRequest(Delete);
                     DeleteResult(obj);
                 }, delegate ()
                 {
                     BeforeRequest(Delete);
                 }
                );
            }
            else
            {
                MessageBox.Show("请选择一项进行删除", "提示");
            }
        }

        private void pagechange_Click(object sender, RoutedEventArgs e)
        {
            UpdatePage(page + 1, true, delegate (int isdone)
             {
                 if (isdone == 0)
                 {
                     MessageBox.Show("无更多数据", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
                 }
                 else if (isdone == -1)
                 {
                     MessageBox.Show("网络错误", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                 }
             });
        }

        private void pagechange_last_Click(object sender, RoutedEventArgs e)
        {
            if (page - 1 >= 0)
            {
                UpdatePage(page - 1);
            }
            else
            {
                MessageBox.Show("已到第一页", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
            }

        }

        protected virtual bool EachArgForAppend(string n, string value)
        {

            return true;
        }
        protected virtual int StandAppendArgsCount
        {
            get => 2 + InputBoxValue.Length * 2;
        }

        protected virtual bool NullablePending(string value)
        {
            return false;
        }

        protected List<ValueTuple<string, string>> CollectData()
        {
            List<ValueTuple<string, string>> r = new List<(string, string)>();
            foreach (var item in inputbox.Items)
            {
                var panel = (InputPanel)item;
                string n = panel.Tag.ToString();
                if (panel.Value == null)
                {
                    if (!NullablePending(n))
                    {
                        MessageBox.Show("空输入错误", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                        break;
                    }

                }
                if (panel.Value.Length > 0)
                {

                    if (!EachArgForAppend(n, panel.Value))
                    {
                        break;
                    }
                    else
                    {
                        r.Add((n, panel.Value));
                        continue;
                    }
                }
                else
                {
                    if (!NullablePending(n))
                    {
                        MessageBox.Show("空输入错误", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                        break;
                    }
                }
            }
            return r;
        }

        protected virtual void add_Click(object sender, RoutedEventArgs e)
        {
            List<string> args = new List<string>(new string[] { TableName, AppendStr(null) });

            foreach (var i in CollectData())
            {
                args.Add(i.Item1);
                args.Add(i.Item2);
            }
            if (args.Count == StandAppendArgsCount)
            {
                SystemManager.Request<int>(SuUserRequestInfo.s_AppendValue, args.ToArray(), SystemManager.Admin, delegate (object obj)
                {
                    AfterRequest(Append);
                    AppendResult(obj);
                }, delegate ()
                {
                    BeforeRequest(Append);
                });
            }
            else
            {
                MessageBox.Show("录入失败，参数错误", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }

        }
        protected virtual bool ValueChangeIsOk(string n, string value)
        {

            return EachArgForAppend(n, value);
        }

        protected virtual void change_Click(object sender, RoutedEventArgs e)
        {
            if (listView.SelectedItem != null)
            {
                var detial = (T)listView.SelectedItem;

                SingleOptionInputBox box = new SingleOptionInputBox(InputBoxTitle);
                var textinput = new InputBox();
                int select = box.Show("请选择要修改的项", "修改");
                if (select >= 0)
                {
                    string value = textinput.Show("请输入要修改的值", "修改");
                    if (value.Length > 0)
                    {
                        if (ValueChangeIsOk(InputBoxValue[select], value))
                            SystemManager.Request<int>(SuUserRequestInfo.s_ChangeValue, new string[] { TableName, ChangeStr(detial), InputBoxValue[select], value }, SystemManager.Admin, delegate (object obj)
                            {
                                AfterRequest(Update);
                                ChangeResult(obj);
                            }, delegate ()
                            {
                                BeforeRequest(Update);
                            });
                        else
                        {
                            MessageBox.Show("修改的值有误", "错误", MessageBoxButton.OK, MessageBoxImage.Error);

                        }
                    }

                    else
                    {
                        MessageBox.Show("空输入错误", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                }
                box.Close();
            }
            else
            {
                MessageBox.Show("请点击一项进行选择", "提示");
            }
        }

    }
}
